<?php
/**
 * DBERP 进销存系统
 *
 * ==========================================================================
 * @link      http://www.dberp.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   http://www.dberp.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Admin\Plugin;

use Admin\Data\Common;
use Customer\Entity\Customer;
use Customer\Entity\CustomerCategory;
use Customer\Entity\Supplier;
use Customer\Entity\SupplierCategory;
use Doctrine\ORM\EntityManager;
use Laminas\Math\Rand;
use Laminas\Mvc\Controller\Plugin\AbstractPlugin;
use Laminas\Session\Container;
use Purchase\Entity\Order;
use Purchase\Entity\WarehouseOrder;
use Sales\Entity\SalesOrder;
use Sales\Entity\SalesSendOrder;
use Stock\Entity\ExWarehouseOrder;
use Stock\Entity\OtherWarehouseOrder;
use Stock\Entity\StockCheck;
use Stock\Entity\StockTransfer;
use Store\Entity\Brand;
use Store\Entity\Goods;
use Store\Entity\GoodsCategory;
use Store\Entity\Warehouse;

class CodeAndNumberPlugin extends AbstractPlugin
{
    private $entityManager;
    private $adminSession;

    private $replaceArray;

    public function __construct(
        EntityManager $entityManager
    )
    {
        $this->entityManager = $entityManager;
        $this->adminSession = new Container('admin');

        $this->replaceArray = [
            '{y}' => date('Y'),
            '{m}' => date('m'),
            '{d}' => date('d'),
            '{h}' => date('H'),
            '{i}' => date('i'),
            '{s}' => date('s'),
            '{loginID}' => strlen($this->adminSession->offsetGet('admin_id')) > 4 ? $this->adminSession->offsetGet('admin_id') : str_pad($this->adminSession->offsetGet('admin_id'), 4, '0', STR_PAD_LEFT),
            '{rand}' => Rand::getString(4, '1234567890'),
        ];
    }

    /**
     * 生成商品编号
     *
     * @return string
     */
    public function createGoodsCode(): string
    {
        $nextId = $this->entityManager->getRepository(Goods::class)->getMaxGoodsId();

        $goodsCodeStr = Common::configValue('code', 'config')['goods'];
        if (empty($goodsCodeStr)) {
            return $this->createCodeStr('G', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $goodsCodeStr);
    }

    /**
     * 生成商品分类编号
     * @return string
     */
    public function createCategoryCode(): string
    {
        $nextId = $this->entityManager->getRepository(GoodsCategory::class)->getMaxCategoryId();

        $categoryCodeStr = Common::configValue('code', 'config')['category'];
        if (empty($categoryCodeStr)) {
            return $this->createCodeStr('C', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $categoryCodeStr);
    }

    /**
     * 生成品牌编号
     * @return string
     */
    public function createBrandCode(): string
    {
        $nextId = $this->entityManager->getRepository(Brand::class)->getMaxBrandId();

        $brandCodeStr = Common::configValue('code', 'config')['brand'];
        if (empty($brandCodeStr)) {
            return $this->createCodeStr('B', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $brandCodeStr);
    }

    /**
     * 生成仓库编号
     * @return string
     */
    public function createWarehouseCode(): string
    {
        $nextId = $this->entityManager->getRepository(Warehouse::class)->getMaxWarehouseId();

        $warehouseCodeStr = Common::configValue('code', 'config')['warehouse'];
        if (empty($warehouseCodeStr)) {
            return $this->createCodeStr('W', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $warehouseCodeStr);
    }

    /**
     * 生成客户编号
     * @return string
     */
    public function createCustomerCode(): string
    {
        $nextId = $this->entityManager->getRepository(Customer::class)->getMaxCustomerId();

        $customerCodeStr = Common::configValue('code', 'config')['customer'];
        if (empty($customerCodeStr)) {
            return $this->createCodeStr('K', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $customerCodeStr);
    }

    /**
     * 生成客户分类编号
     * @return string
     */
    public function createCustomerCategoryCode(): string
    {
        $nextId = $this->entityManager->getRepository(CustomerCategory::class)->getMaxCustomerCategoryId();

        $customerCategoryCodeStr = Common::configValue('code', 'config')['customer_category'];
        if (empty($customerCategoryCodeStr)) {
            return $this->createCodeStr('KF', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $customerCategoryCodeStr);
    }

    /**
     * 生成供应商编号
     * @return string
     */
    public function createSupplierCode(): string
    {
        $nextId = $this->entityManager->getRepository(Supplier::class)->getMaxSupplierId();

        $supplierCodeStr = Common::configValue('code', 'config')['supplier'];
        if (empty($supplierCodeStr)) {
            return $this->createCodeStr('S', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $supplierCodeStr);
    }

    /**
     * 生成供应商分类编号
     * @return string
     */
    public function createSupplierCategoryCode(): string
    {
        $nextId = $this->entityManager->getRepository(SupplierCategory::class)->getMaxSupplierCategoryId();

        $supplierCategoryCodeStr = Common::configValue('code', 'config')['supplier_category'];
        if (empty($supplierCategoryCodeStr)) {
            return $this->createCodeStr('SF', ['type' => 'code', 'nextId' => $nextId]);
        }

        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $supplierCategoryCodeStr);
    }

    /**
     * 生成其他入库单号
     * @return string
     */
    public function createStockInCode(): string
    {
        $stockInCodeStr = Common::configValue('code', 'config')['stock_in'];
        if (empty($stockInCodeStr)) {
            return $this->createCodeStr('O');
        }

        $nextId = $this->entityManager->getRepository(OtherWarehouseOrder::class)->getMaxStockInId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $stockInCodeStr);
    }

    /**
     * 生成其他出库单号
     * @return string
     */
    public function createStockOutCode(): string
    {
        $stockExCodeStr = Common::configValue('code', 'config')['stock_ex'];
        if (empty($stockExCodeStr)) {
            return $this->createCodeStr('E');
        }

        $nextId = $this->entityManager->getRepository(ExWarehouseOrder::class)->getMaxStockExId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $stockExCodeStr);
    }

    /**
     * 生成库存盘点单号
     * @return string
     */
    public function createStockCheckCode(): string
    {
        $stockCheckCodeStr = Common::configValue('code', 'config')['stock_check'];
        if (empty($stockCheckCodeStr)) {
            return $this->createCodeStr('N');
        }

        $nextId = $this->entityManager->getRepository(StockCheck::class)->getMaxStockCheckId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $stockCheckCodeStr);
    }

    /**
     * 生成库存调拨单号
     * @return string
     */
    public function createStockTransferCode(): string
    {
        $stockTransferCodeStr = Common::configValue('code', 'config')['stock_transfer'];
        if (empty($stockTransferCodeStr)) {
            return $this->createCodeStr('D');
        }

        $nextId = $this->entityManager->getRepository(StockTransfer::class)->getMaxStockTransferId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 4, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $stockTransferCodeStr);
    }

    /**
     * 生成采购订单号
     * @return string
     */
    public function createPurchaseOrderCode(): string
    {
        $purchaseOrderCodeStr = Common::configValue('code', 'config')['purchase_order'];
        if (empty($purchaseOrderCodeStr)) {
            return $this->createCodeStr('P');
        }

        $nextId = $this->entityManager->getRepository(Order::class)->getMaxOrderId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 6, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $purchaseOrderCodeStr);
    }

    /**
     * 生成采购入库单号
     * @return string
     */
    public function createWarehouseOrderCode(): string
    {
        $warehouseOrderCodeStr = Common::configValue('code', 'config')['warehouse_order'];
        if (empty($warehouseOrderCodeStr)) {
            return $this->createCodeStr('W');
        }

        $nextId = $this->entityManager->getRepository(WarehouseOrder::class)->getMaxWarehouseOrderId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 6, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $warehouseOrderCodeStr);
    }

    /**
     * 生成销售订单号
     * @return string
     */
    public function createSalesOrderCode(): string
    {
        $salesOrderCodeStr = Common::configValue('code', 'config')['sales_order'];
        if (empty($salesOrderCodeStr)) {
            return $this->createCodeStr('S');
        }

        $nextId = $this->entityManager->getRepository(SalesOrder::class)->getMaxSalesOrderId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 6, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $salesOrderCodeStr);
    }

    /**
     * 生成销售发货单号
     * @return string
     */
    public function createSendOrderCode(): string
    {
        $sendOrderCodeStr = Common::configValue('code', 'config')['sales_send_order'];
        if (empty($sendOrderCodeStr)) {
            return $this->createCodeStr('H');
        }

        $nextId = $this->entityManager->getRepository(SalesSendOrder::class)->getMaxSendOrderId();
        $this->replaceArray['{nextID}'] = str_pad($nextId, 6, '0', STR_PAD_LEFT);

        return str_replace(array_keys($this->replaceArray), array_values($this->replaceArray), $sendOrderCodeStr);
    }

    /**
     * 当没有设置时默认生成的单号和编号
     * @param $prefix
     * @param array $array
     * @return string
     */
    private function createCodeStr($prefix, array $array = []): string
    {
        if ($array['type'] == 'code') {

            return $prefix . '-' . Rand::getString(4, '1234567890') . '-' . $array['nextId'];
        }

        $adminId = $this->adminSession->offsetGet('admin_id');
        return $prefix . (strlen($adminId) > 3 ? substr($adminId, -3) : str_pad($adminId, 3, '0', STR_PAD_LEFT)) . date("YmdHis", time());
    }
}